using System.ComponentModel.DataAnnotations;
using System.Runtime.CompilerServices;

namespace KinonekoSoftware.CodariaDB.Documents.Timelines
{
    using System.Runtime.InteropServices;

    /// <summary>
    /// <see cref="Epoch"/> 类型表示时期，不同时期
    /// </summary>
    public sealed class Epoch : RootObject, IComparable<Epoch>
    {
        private string _name;
        private string _color;
        private bool   _isLastOne;
        private uint   _value;

        public static unsafe uint Inherit(Epoch epoch, byte value)
        {
            var   index    = Math.Clamp(4 - epoch.Tier, 0, 3);
            var   newValue = epoch._value;
            
            void* ptr      = &newValue;
            var   p        = (byte*)ptr;
            p[index] = value;

            return newValue;
        }

        public static unsafe uint Tier1(byte index)
        {
            uint  val = 0;
            void* ptr = &val;
            var   p   = (byte*)ptr;

            p[3] = index;

            return val;
        }

        public static unsafe uint Tier2(byte t1, byte t2)
        {
            uint  val = 0;
            void* ptr = &val;
            var   p   = (byte*)ptr;

            p[3] = t1;
            p[2] = t2;
            return val;
        }

        public static unsafe uint Tier3(byte t1, byte t2, byte t3)
        {
            uint  val = 0;
            void* ptr = &val;
            var   p   = (byte*)ptr;

            p[3] = t1;
            p[2] = t2;
            p[1] = t3;

            return val;
        }

        public static unsafe uint Tier4(byte t1, byte t2, byte t3, byte t4)
        {
            uint  val = 0;
            void* ptr = &val;
            var   p   = (byte*)ptr;

            p[3] = t1;
            p[2] = t2;
            p[1] = t3;
            p[0] = t4;

            return val;
        }

        public int CompareTo(Epoch other)
        {
            //
            // 

            if (other is null)
            {
                return 1;
            }

            var v = (int)(Value - other.Value);

            return v == 0 ? 
                0 :
                v < 0 ? 
                    -1 :
                    1;
        }

        public string Color
        {
            get => _color;
            set => SetValue(ref _color, value);
        }

        public string Name
        {
            get => _name;
            set => SetValue(ref _name, value);
        }

        [BsonIgnore]
        public bool IsLastOne
        {
            get => _isLastOne;
            set => SetValue(ref _isLastOne, value);
        }

        public string ParentID { get;           set; }
        public byte   Tier     { get;           set; }
        public uint   Value    { get => _value; set => _value = value; }
    }
}